package com.gitee.qdbp.general.common.biz.settings.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitee.qdbp.able.beans.KeyString;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.general.common.api.settings.model.AreaBean;
import com.gitee.qdbp.general.common.api.settings.model.AreaDivisionBean;
import com.gitee.qdbp.general.common.enums.AreaType;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.StringTools;
import com.gitee.qdbp.tools.utils.VerifyTools;

public class AreaDivisionTools {

    private static final Logger log = LoggerFactory.getLogger(AreaDivisionTools.class);

    private static String PROVINCES = "北京市|上海市|天津市|重庆市|江苏省|浙江省|安徽省|湖南省|湖北省|广东省|广西壮族自治区|"
            + "四川省|福建省|江西省|河南省|河北省|山东省|山西省|辽宁省|吉林省|黑龙江省|内蒙古自治区|海南省|贵州省|云南省|陕西省|"
            + "甘肃省|青海省|宁夏回族自治区|西藏自治区|新疆维吾尔自治区|香港特别行政区|澳门特别行政区|台湾省";

    /** 省级行政单位的排序 **/
    private static Map<String, Integer> PROVINCE_SORT_INDEX_MAP = new HashMap<>();
    /** 简称 **/
    private static Map<String, String> SHORT_NAME_MAP = new HashMap<>();
    static {
        SHORT_NAME_MAP.put("中华人民共和国", "中国");
        SHORT_NAME_MAP.put("广西壮族自治区", "广西");
        SHORT_NAME_MAP.put("宁夏回族自治区", "宁夏");
        SHORT_NAME_MAP.put("西藏自治区", "西藏");
        SHORT_NAME_MAP.put("新疆维吾尔自治区", "新疆");
        SHORT_NAME_MAP.put("内蒙古自治区", "内蒙古");
        SHORT_NAME_MAP.put("香港特别行政区", "香港");
        SHORT_NAME_MAP.put("澳门特别行政区", "澳门");

        String[] array = StringTools.split(PROVINCES);
        for (int i = 0; i < array.length; i++) {
            PROVINCE_SORT_INDEX_MAP.put(array[i], i + 1);
        }
    }

    public static <T extends AreaBean> String getAreaText(String areaCode, Map<String, T> areas) {
        if (areas == null) return null;
        // 有些行政区划不是完全标准的, 上级编号不一定是下级编号前几位补0
        // List<String> codes = CodeTools.split(areaCode, 2, true);
        // StringBuilder buffer = new StringBuilder();
        // String parentName = null;
        // String parentCode = null;
        // for (String item : codes) {
        //     String code = StringTools.pad(item, '0', false, 6);
        //     if (parentCode != null && parentCode.equals(code)) {
        //         continue;
        //     }
        //     AreaBean area = areas.get(code);
        //     if (area == null) {
        //         continue;
        //     }
        //     String shortName = getShortName(area);
        //     if (parentName != null && parentName.equals(shortName)) {
        //         continue;
        //     }
        //     if (buffer.length() > 0) {
        //         buffer.append(" ");
        //     }
        //     buffer.append(shortName);
        //     parentName = shortName;
        //     parentCode = code;
        // }
        // return buffer.toString();

        ArrayList<String> buffer = new ArrayList<>();
        String tempCode = areaCode;
        String lastName = null;
        while (tempCode != null) {
            AreaBean bean = areas.get(tempCode);
            if (bean == null || bean.getType() == AreaType.COUNTRY) {
                break;
            }
            String shortName = getShortName(bean);
            if (lastName == null || !lastName.equals(shortName)) {
                buffer.add(0, shortName);
            }
            tempCode = bean.getParentCode();
            lastName = shortName;
        }
        return buffer.isEmpty() ? null : ConvertTools.joinToString(buffer, " ");
    }

    public static <T extends AreaBean> List<KeyString> getAreaText(List<String> areaCodes, Map<String, T> areas) {
        if (areaCodes == null) return null;

        List<KeyString> list = new ArrayList<>();
        for (String areaCode : areaCodes) {
            String areaText = getAreaText(areaCode, areas);
            list.add(new KeyString(areaCode, areaText));
        }
        return list;
    }

    public static String getShortName(AreaBean area) {
        if (VerifyTools.isNotBlank(area.getShortName())) {
            return area.getShortName();
        } else {
            return area.getAreaName();
        }
    }

    /**
     * 生成行政区划简称
     * 
     * @param areaName 行政区划全称
     * @param areaType 行政区划类型
     * @param unchangedReturnNull 如果没有简称, 是返回null还是返回全称
     * @return 简称
     */
    public static String generateShortName(String areaName, AreaType areaType, boolean unchangedReturnNull) {
        String shortName = null;
        if (areaType == AreaType.COUNTRY) {
            shortName = SHORT_NAME_MAP.get(areaName);
        } else if (areaType == AreaType.PROVINCE) {
            if (SHORT_NAME_MAP.containsKey(areaName)) {
                shortName = SHORT_NAME_MAP.get(areaName);
            } else {
                shortName = StringTools.removeRight(areaName, '省', '市');
            }
        } else if (areaType == AreaType.CITY) {
            if (SHORT_NAME_MAP.containsKey(areaName)) {
                shortName = SHORT_NAME_MAP.get(areaName);
            } else {
                shortName = StringTools.removeRight(areaName, '市');
            }
        } else if (areaType == AreaType.DISTRICT) {
            shortName = StringTools.removeRight(areaName, '市', '区', '县');
        } else if (areaType == AreaType.TOWNSHIP) {
            // 暂不支持TOWNSHIP
            // shortName = StringTools.removeSuffix(areaName, "街道", "镇", "乡");
        }

        if (unchangedReturnNull) {
            return areaName.equals(shortName) ? null : shortName;
        } else {
            return shortName == null ? areaName : shortName;
        }
    }

    public static void fillShortName(AreaBean area, boolean force) {
        if (force || VerifyTools.isBlank(area.getShortName())) {
            String areaName = area.getAreaName();
            AreaType areaType = area.getType();
            if (areaType == AreaType.COUNTRY || areaType == AreaType.PROVINCE || areaType == AreaType.CITY) {
                area.setShortName(generateShortName(areaName, areaType, true));
            }
        }
    }

    public static void fillSortIndex(AreaBean area, boolean force) {
        if (force || area.getSortIndex() == null) {
            String areaCode = area.getAreaCode();
            Integer sortIndex = null;
            try {
                if (area.getType() == AreaType.PROVINCE) {
                    if (PROVINCE_SORT_INDEX_MAP.containsKey(area.getAreaName())) {
                        sortIndex = PROVINCE_SORT_INDEX_MAP.get(area.getAreaName());
                    } else {
                        sortIndex = ConvertTools.toInteger(areaCode.substring(0, 2), null);
                    }
                } else if (area.getType() == AreaType.CITY) {
                    sortIndex = ConvertTools.toInteger(areaCode.substring(2, 4), null);
                } else if (area.getType() == AreaType.DISTRICT) {
                    sortIndex = ConvertTools.toInteger(areaCode.substring(4, 6), null);
                }
            } catch (Exception ignore) {
            }
            if (sortIndex != null) {
                area.setSortIndex(sortIndex);
            } else if (area.getSortIndex() == null) {
                area.setSortIndex(1);
            }
        }
    }

    /** 静态检查参数格式, 不涉及数据库操作 **/
    public static void staticCheckCreateModel(AreaBean model, String msg) throws ServiceException {

        // 参数验证
        if (VerifyTools.isBlank(model.getAreaCode())) {
            log.error(msg + "params is null: AreaCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getAreaName())) {
            log.error(msg + "params is null: AreaName");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model.getParentCode())) {
            log.error(msg + "params is null: ParentCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (model instanceof AreaDivisionBean) {
            AreaDivisionBean real = (AreaDivisionBean) model;
            real.setId(null); // 主键由Basic生成, 不允许外部传入
            if (VerifyTools.isBlank(real.getSceneType())) {
                log.error(msg + "params is null: SceneType");
                throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
            }
        }
    }

    /** 静态检查区域编号 **/
    public static void staticCheckAreaCode(AreaBean model, String msg) throws ServiceException {
        String areaCode = model.getAreaCode();
        if (VerifyTools.isBlank(areaCode)) {
            log.error(msg + "params is null: AreaCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        String parentCode = model.getParentCode();
        if (VerifyTools.isBlank(parentCode)) {
            log.error(msg + "params is null: ParentCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        AreaType type = model.getType();
        if (VerifyTools.isBlank(type)) {
            log.error(msg + "params is null: AreaType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
    }
}
